package com.chengyi.serialport.demo.utils

import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.text.TextUtils
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.BitmapImageViewTarget
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.chengyi.serialport.demo.R
import com.luck.picture.lib.PictureSelectorPreviewFragment
import com.luck.picture.lib.basic.*
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.config.SelectModeConfig
import com.luck.picture.lib.engine.*
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnCallbackIndexListener
import com.luck.picture.lib.interfaces.OnCallbackListener
import com.luck.picture.lib.interfaces.OnInjectLayoutResourceListener
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.luck.picture.lib.manager.PictureCacheManager
import com.luck.picture.lib.style.BottomNavBarStyle
import com.luck.picture.lib.style.PictureSelectorStyle
import com.luck.picture.lib.style.SelectMainStyle
import com.luck.picture.lib.style.TitleBarStyle
import com.luck.picture.lib.utils.*
import com.wyj.utils.AppConfig
import com.wyj.utils.BitmapUtils
import com.wyj.utils.FileUtils
import com.yalantis.ucrop.UCrop
import com.yalantis.ucrop.UCropImageEngine
import top.zibin.luban.Luban
import top.zibin.luban.OnCompressListener
import java.io.File
import java.io.FileOutputStream

val LocalMedia.mPath: String?
    get() {
        return when {
            this.isCut -> {
                this.cutPath
            }
            this.isOriginal -> {
                this.originalPath
            }
            this.isCompressed -> {
                this.compressPath
            }
            !TextUtils.isEmpty(this.sandboxPath) -> {
                this.sandboxPath
            }
            else -> this.path
        }
    }

object PictureSelectorHelp {
    class GlideEngine private constructor() : ImageEngine {

        override fun loadImage(context: Context, url: String, imageView: ImageView) {
            if (!ActivityCompatHelper.assertValidRequest(context)) {
                return
            }
            Glide.with(context).load(url).into(imageView)
        }

        override fun loadImage(context: Context, imageView: ImageView, url: String?, maxWidth: Int, maxHeight: Int) {
            if (!ActivityCompatHelper.assertValidRequest(context)) {
                return
            }
            Glide.with(context).load(url).override(maxWidth, maxHeight).into(imageView)
        }


        /**
         * 加载相册目录封面
         *
         * @param context   上下文
         * @param url       图片路径
         * @param imageView 承载图片ImageView
         */
        override fun loadAlbumCover(context: Context, url: String, imageView: ImageView) {
            if (!ActivityCompatHelper.assertValidRequest(context)) {
                return
            }

            Glide.with(context).asBitmap().load(url).override(180, 180).centerCrop().sizeMultiplier(0.5f).placeholder(R.drawable.ps_image_placeholder).into(object : BitmapImageViewTarget(imageView) {
                override fun setResource(resource: Bitmap?) {
                    val circularBitmapDrawable = RoundedBitmapDrawableFactory.create(context.resources, resource)
                    circularBitmapDrawable.cornerRadius = 8f
                    imageView.setImageDrawable(circularBitmapDrawable)
                }
            })
        }


        /**
         * 加载图片列表图片
         *
         * @param context   上下文
         * @param url       图片路径
         * @param imageView 承载图片ImageView
         */
        override fun loadGridImage(context: Context, url: String, imageView: ImageView) {
            if (!ActivityCompatHelper.assertValidRequest(context)) {
                return
            }
            Glide.with(context).load(url).override(200, 200).centerCrop().placeholder(R.drawable.ps_image_placeholder).into(imageView)
        }

        override fun pauseRequests(context: Context?) {
            Glide.with(context!!).pauseRequests()
        }

        override fun resumeRequests(context: Context?) {
            Glide.with(context!!).resumeRequests()
        }


        companion object {
            @JvmStatic
            private val instance: GlideEngine = GlideEngine()

            @JvmStatic
            fun createGlideEngine(): GlideEngine = instance
        }
    }

    class PictureSelectorEngineImp : PictureSelectorEngine {
        override fun createImageLoaderEngine(): ImageEngine? {
            return GlideEngine.createGlideEngine()
        }

        override fun createCompressEngine(): CompressEngine? {
            return ImageCompressEngine(150)
        }

        override fun createCompressFileEngine(): CompressFileEngine? {
            return null
        }

        override fun createLoaderDataEngine(): ExtendLoaderEngine? {
            return null
        }

        override fun createVideoPlayerEngine(): VideoPlayerEngine<*>? {
            return null
        }

        override fun onCreateLoader(): IBridgeLoaderFactory? {
            return null
        }

        override fun createSandboxFileEngine(): SandboxFileEngine? {
            return MeSandboxFileEngine()
        }

        override fun createUriToFileTransformEngine(): UriToFileTransformEngine? {
            return null
        }

        override fun createLayoutResourceListener(): OnInjectLayoutResourceListener? {
            return null
        }

        override fun getResultCallbackListener(): OnResultCallbackListener<LocalMedia>? {
            return null
        }
    }

    private class MeSandboxFileEngine : SandboxFileEngine {
        override fun onStartSandboxFileTransform(context: Context, isOriginalImage: Boolean, index: Int, media: LocalMedia, listener: OnCallbackIndexListener<LocalMedia>) {
            if (PictureMimeType.isContent(media.availablePath)) {
                media.sandboxPath = SandboxTransformUtils.copyPathToSandbox(context, media.path, media.mimeType)
            }
            if (isOriginalImage) {
                val originalPath = SandboxTransformUtils.copyPathToSandbox(context, media.path, media.mimeType)
                media.originalPath = originalPath
                media.isOriginal = !TextUtils.isEmpty(originalPath)
            }
            listener.onCall(media, index)
        }
    }

    private class ImageCompressEngine(private val ignoreBy: Int) : CompressEngine {
        override fun onStartCompress(context: Context, list: ArrayList<LocalMedia>, listener: OnCallbackListener<ArrayList<LocalMedia>>) {
            // 自定义压缩
            val compress: MutableList<Uri> = ArrayList()
            for (i in list.indices) {
                val media = list[i]
                val availablePath = media.availablePath
                val uri = if (PictureMimeType.isContent(availablePath) || PictureMimeType.isHasHttp(availablePath)) Uri.parse(availablePath) else Uri.fromFile(File(availablePath))
                compress.add(uri)
            }
            if (compress.size == 0) {
                listener.onCall(list)
                return
            }
            Luban.with(context).load(compress).ignoreBy(ignoreBy).filter { path -> PictureMimeType.isUrlHasImage(path) && !PictureMimeType.isHasHttp(path) }.setRenameListener { filePath ->
                val indexOf = filePath.lastIndexOf(".")
                val postfix = if (indexOf != -1) filePath.substring(indexOf) else ".jpg"
                DateUtils.getCreateFileName("CMP_") + postfix
            }.setCompressListener(object : OnCompressListener {
                override fun onStart() {}
                override fun onSuccess(index: Int, compressFile: File) {
                    val media = list[index]
                    if (compressFile.exists() && !TextUtils.isEmpty(compressFile.absolutePath)) {
                        media.isCompressed = true
                        media.compressPath = compressFile.absolutePath
                        media.sandboxPath = if (SdkVersionUtils.isQ()) media.compressPath else null
                    }
                    if (index == list.size - 1) {
                        listener.onCall(list)
                    }
                }

                override fun onError(index: Int, e: Throwable) {
                    if (index != -1) {
                        val media = list[index]
                        media.isCompressed = false
                        media.compressPath = null
                        media.sandboxPath = null
                        if (index == list.size - 1) {
                            listener.onCall(list)
                        }
                    }
                }
            }).launch()
        }
    }

    private class ImageCropEngine(private val options: UCrop.Options) : CropEngine {
        override fun onStartCrop(fragment: Fragment?, currentLocalMedia: LocalMedia, dataSource: ArrayList<LocalMedia>?, requestCode: Int) {
            val currentCropPath = currentLocalMedia?.availablePath ?: return
            val inputUri = if (PictureMimeType.isContent(currentCropPath) || PictureMimeType.isHasHttp(currentCropPath)) {
                Uri.parse(currentCropPath)
            } else {
                Uri.fromFile(File(currentCropPath))
            }
            val fileName = DateUtils.getCreateFileName("CROP_") + ".jpg"
            FileUtils.createNewFile("${AppConfig.DEFAULT.PICTURE_SELECTOR_DIR}/${fileName}")
            val destinationUri = Uri.fromFile(File(AppConfig.DEFAULT.PICTURE_SELECTOR_DIR, fileName))
            val dataCropSource = ArrayList<String>()
            dataSource?.forEach { media ->
                dataCropSource.add(media.availablePath)
            }
            val uCrop = UCrop.of(inputUri, destinationUri, dataCropSource).withOptions(options)
            //options.setMultipleCropAspectRatio(buildAspectRatios(dataSource.size()));
            //options.setMultipleCropAspectRatio(buildAspectRatios(dataSource.size()));
            uCrop.setImageEngine(object : UCropImageEngine {
                override fun loadImage(context: Context, url: String, imageView: ImageView) {
                    if (!ActivityCompatHelper.assertValidRequest(context)) {
                        return
                    }
                    Glide.with(context).load(url).into(imageView)
                }

                override fun loadImage(context: Context, url: Uri, maxWidth: Int, maxHeight: Int, call: UCropImageEngine.OnCallbackListener<Bitmap>?) {
                    if (!ActivityCompatHelper.assertValidRequest(context)) {
                        return
                    }
                    Glide.with(context).asBitmap().override(maxWidth, maxHeight).load(url).into(object : CustomTarget<Bitmap?>() {
                        override fun onLoadFailed(errorDrawable: Drawable?) {
                            call?.onCall(null)
                        }

                        override fun onLoadCleared(placeholder: Drawable?) {}
                        override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap?>?) {
                            call?.onCall(resource)
                        }
                    })
                }
            })
            if (fragment != null) {
                uCrop.start(fragment.activity ?: return, fragment, requestCode)
            }
        }

    }

    private fun createWeixinStyle(context: Context): PictureSelectorStyle {
        val numberSelectMainStyle = SelectMainStyle()
        numberSelectMainStyle.isSelectNumberStyle = true
        numberSelectMainStyle.isPreviewSelectNumberStyle = false
        numberSelectMainStyle.isPreviewDisplaySelectGallery = true
        numberSelectMainStyle.selectBackground = R.drawable.ps_default_num_selector
        numberSelectMainStyle.previewSelectBackground = R.drawable.ps_preview_checkbox_selector
        numberSelectMainStyle.selectNormalBackgroundResources = R.drawable.ps_select_complete_normal_bg
        numberSelectMainStyle.selectNormalTextColor = ContextCompat.getColor(context, R.color.ps_color_53575e)
        numberSelectMainStyle.selectNormalText = context.getString(R.string.ps_send)
        numberSelectMainStyle.adapterPreviewGalleryBackgroundResource = R.drawable.ps_preview_gallery_bg
        numberSelectMainStyle.adapterPreviewGalleryItemSize = DensityUtil.dip2px(context, 52f)
        numberSelectMainStyle.previewSelectText = context.getString(R.string.ps_select)
        numberSelectMainStyle.previewSelectTextSize = 14
        numberSelectMainStyle.previewSelectTextColor = ContextCompat.getColor(context, R.color.ps_color_white)
        numberSelectMainStyle.previewSelectMarginRight = DensityUtil.dip2px(context, 6f)
        numberSelectMainStyle.selectBackgroundResources = R.drawable.ps_select_complete_bg
        numberSelectMainStyle.selectText = context.getString(R.string.ps_send_num)
        numberSelectMainStyle.selectTextColor = ContextCompat.getColor(context, R.color.ps_color_white)
        numberSelectMainStyle.mainListBackgroundColor = ContextCompat.getColor(context, R.color.ps_color_black)
        numberSelectMainStyle.isCompleteSelectRelativeTop = true
        numberSelectMainStyle.isPreviewSelectRelativeBottom = true
        numberSelectMainStyle.isAdapterItemIncludeEdge = false
        // 头部TitleBar 风格
        val numberTitleBarStyle = TitleBarStyle()
        numberTitleBarStyle.isHideCancelButton = true
        numberTitleBarStyle.isAlbumTitleRelativeLeft = true
        numberTitleBarStyle.titleAlbumBackgroundResource = R.drawable.ps_album_bg
        numberTitleBarStyle.titleDrawableRightResource = R.drawable.ps_ic_grey_arrow
        numberTitleBarStyle.previewTitleLeftBackResource = R.drawable.ps_ic_normal_back
        // 底部NavBar 风格
        val numberBottomNavBarStyle = BottomNavBarStyle()
        numberBottomNavBarStyle.bottomPreviewNarBarBackgroundColor = ContextCompat.getColor(context, R.color.ps_color_half_grey)
        numberBottomNavBarStyle.bottomPreviewNormalText = context.getString(R.string.ps_preview)
        numberBottomNavBarStyle.bottomPreviewNormalTextColor = ContextCompat.getColor(context, R.color.ps_color_9b)
        numberBottomNavBarStyle.bottomPreviewNormalTextSize = 16
        numberBottomNavBarStyle.isCompleteCountTips = false
        numberBottomNavBarStyle.bottomPreviewSelectText = context.getString(R.string.ps_preview_num)
        numberBottomNavBarStyle.bottomPreviewSelectTextColor = ContextCompat.getColor(context, R.color.ps_color_white)
        val selectorStyle = PictureSelectorStyle()
        selectorStyle.titleBarStyle = numberTitleBarStyle
        selectorStyle.bottomBarStyle = numberBottomNavBarStyle
        selectorStyle.selectMainStyle = numberSelectMainStyle
        return selectorStyle
    }

    @JvmStatic
    private fun setDefaultConfig(context: Context, config: PictureSelectionPreviewModel): PictureSelectionPreviewModel {
        return config.setSelectorUIStyle(createWeixinStyle(context)).setImageEngine(GlideEngine.createGlideEngine())
            .isPreviewFullScreenMode(true)
    }

    @JvmStatic
     fun setDefaultConfig(config: PictureSelectionCameraModel): PictureSelectionCameraModel {
        return config.setCompressEngine(ImageCompressEngine(150)).setSandboxFileEngine(MeSandboxFileEngine())
            .setOutputAudioDir(AppConfig.DEFAULT.PICTURE_SELECTOR_DIR).setOutputCameraDir(AppConfig.DEFAULT.PICTURE_SELECTOR_DIR)
            .isOriginalControl(false)
    }

    @JvmStatic
    private fun setDefaultConfig(context: Context, config: PictureSelectionModel): PictureSelectionModel {
        return config.setSelectorUIStyle(createWeixinStyle(context)).setImageEngine(GlideEngine.createGlideEngine())
            .setCompressEngine(ImageCompressEngine(150)).setSandboxFileEngine(MeSandboxFileEngine())
            .setOutputAudioDir(AppConfig.DEFAULT.PICTURE_SELECTOR_DIR).setOutputCameraDir(AppConfig.DEFAULT.PICTURE_SELECTOR_DIR).setQuerySandboxDir(AppConfig.DEFAULT.PICTURE_SELECTOR_DIR)
            .isDisplayTimeAxis(true).isPageStrategy(true).isOriginalControl(false).isDisplayCamera(true)
            .isPreviewFullScreenMode(true).isPreviewZoomEffect(true).isPreviewImage(true).isPreviewVideo(true)
            .isPreviewAudio(false).isMaxSelectEnabledMask(true).isDirectReturnSingle(false).isGif(true)

    }
    @JvmStatic
    fun showSelector(activity: Activity, selectMimeType: Int = SelectMimeType.ofImage(), selectedList: List<LocalMedia>? = null, listener: OnResultCallbackListener<LocalMedia>) {
        val config = setDefaultConfig(activity, PictureSelector.create(activity).openGallery(selectMimeType)).setSelectionMode(SelectModeConfig.SINGLE)
        if (selectedList != null) {
            config.setSelectedData(selectedList)
        }
        config.setPreviewInterceptListener { context, position, totalNum, page, currentBucketId, currentAlbumName, isShowCamera, data, isBottomPreview ->
            val fragmentManager = (context as? FragmentActivity)?.supportFragmentManager
            if (fragmentManager != null) {
                val previewFragment = PictureSelectorPreviewFragment.newInstance()
                previewFragment.setInternalPreviewData(isBottomPreview, currentAlbumName, isShowCamera, position, totalNum, page, currentBucketId, data)
                FragmentInjectManager.injectSystemRoomFragment(fragmentManager, PictureSelectorPreviewFragment.TAG, previewFragment)
            }
        }.buildLaunch(android.R.id.content, listener)
    }


    @JvmStatic
    fun showCamera(activity: Activity, request: Int) {
        setDefaultConfig(PictureSelector.create(activity).openCamera(SelectMimeType.ofImage()))
    }

    @JvmStatic
    fun showSelector(activity: Activity, selectedList: List<LocalMedia>? = null, listener: OnResultCallbackListener<LocalMedia>) {
        val config = setDefaultConfig(activity, PictureSelector.create(activity).openGallery(SelectMimeType.ofImage())).setSelectionMode(SelectModeConfig.SINGLE)
        if (selectedList != null) {
            config.setSelectedData(selectedList)
        }
        config.forResult(listener)
    }

    @JvmStatic
    fun showCamera(activity: Activity, listener: OnResultCallbackListener<LocalMedia>) {
        setDefaultConfig(PictureSelector.create(activity).openCamera(SelectMimeType.ofImage())).forResult(listener)
    }

    @JvmStatic
    @JvmOverloads
    fun showSelectors(activity: Activity, request: Int, selectedList: List<LocalMedia>? = null, maxSelectNum: Int = 9) {
        val config = setDefaultConfig(activity, PictureSelector.create(activity).openGallery(SelectMimeType.ofImage())).setMaxSelectNum(maxSelectNum).setSelectionMode(SelectModeConfig.MULTIPLE)
        if (selectedList != null) {
            config.setSelectedData(selectedList)
        }
        config.forResult(request)
    }

    @JvmStatic
    @JvmOverloads
    fun showSelectors(activity: Activity, listener: OnResultCallbackListener<LocalMedia>, selectedList: List<LocalMedia>? = null, maxSelectNum: Int = 9) {
        val config = setDefaultConfig(activity, PictureSelector.create(activity).openGallery(SelectMimeType.ofImage())).setMaxSelectNum(maxSelectNum).setSelectionMode(SelectModeConfig.MULTIPLE)
        if (selectedList != null) {
            config.setSelectedData(selectedList)
        }
        config.forResult(listener)
    }

    @JvmStatic
    fun clearCache(context: Context) {
        PictureCacheManager.deleteAllCacheDirFile(context)
    }

    @JvmStatic
    fun showCropSelector(activity: Activity, request: Int) {
        setDefaultConfig(activity, PictureSelector.create(activity).openGallery(SelectMimeType.ofImage())).setSelectionMode(SelectModeConfig.SINGLE).isOriginalControl(false).setCropEngine(ImageCropEngine(UCrop.Options().also {
            it.withAspectRatio(120f, 120f)
        })).forResult(request)
    }

    @JvmStatic
    fun showCropSelector(activity: Activity, listener: OnResultCallbackListener<LocalMedia>) {
        setDefaultConfig(activity, PictureSelector.create(activity).openGallery(SelectMimeType.ofImage())).setSelectionMode(SelectModeConfig.SINGLE).isOriginalControl(false).setCropEngine(ImageCropEngine(UCrop.Options().also {
            it.withAspectRatio(120f, 120f)
        })).forResult(listener)
    }

    @JvmStatic
    fun startActivityPreview(context: Context, previewImageRes: Int) {
        ContextCompat.getDrawable(context, previewImageRes)?.let {
            startActivityPreview(context, it)
        }
    }

    @JvmStatic
    fun startActivityPreview(context: Context, previewImage: Drawable) {
        resource2File(previewImage, "${AppConfig.DEFAULT.PICTURE_SELECTOR_DIR}/${System.currentTimeMillis()}.png") {
            if (context is Activity) {
                startActivityPreview(context, it)
            }
        }
    }

    @JvmStatic
    fun resource2File(context: Context, previewImageRes: Int, path: String, callback: (String) -> Unit) {
        ContextCompat.getDrawable(context, previewImageRes)?.let {
            resource2File(it, path, callback)
        }
    }

    @JvmStatic
    fun resource2File(previewImage: Drawable, path: String, callback: (String) -> Unit) {
        val copyFileSuccess = PictureFileUtils.writeFileFromIS(BitmapUtils.bitmap2InputStream(BitmapUtils.drawable2Bitmap(previewImage)), FileOutputStream(path))
        if (copyFileSuccess) {
            callback.invoke(path)
        }
    }


    @JvmStatic
    @JvmOverloads
    fun startActivityPreview(activity: Activity, vararg urls: String, position: Int = 0) {
        val list = ArrayList<LocalMedia>()
        for (url in urls) {
            if (TextUtils.isEmpty(url)) {
                continue
            }
            val item = LocalMedia()
            item.path = url
            list.add(item)
        }
        if (list.isNotEmpty()) {
            setDefaultConfig(activity, PictureSelector.create(activity).openPreview()).startActivityPreview(position, false, list)
        }
    }

    @JvmStatic
    @JvmOverloads
    fun startFragmentPreview(activity: FragmentActivity, vararg urls: String, position: Int = 0) {
        val list = ArrayList<LocalMedia>()
        for (url in urls) {
            if (TextUtils.isEmpty(url)) {
                continue
            }
            val item = LocalMedia()
            item.path = url
            list.add(item)
        }
        if (list.isNotEmpty()) {
            setDefaultConfig(activity, PictureSelector.create(activity).openPreview()).startFragmentPreview(position, false, list)
        }
    }
}
